expry
expry
is a fast schemaless binary format for data, with the ability for filtering and selecting parts of the information using expressions over the stored binary data. Expressions are compiled and optimized to bytecode, and during evaluation this bytecode is interpreted.
JSON can be read into these data structures (using DecodedValue::parse_json
).
The following data types are supported:
null
;bool
;int64
;float
;double
;string
;array
;object
.
Expressions
Expressions over binary objects are compiled to byte code, and can be transmitted over the network. This bytecode can be quickly evaluated, as the bytecode is optimized on the way the binary objects are stored on a low level. Keys inside objects are stored in an ordered way. If keys are not needed any more for evaluation of the current expression, they are permanently skipped.
- Constants:
null
,false
,true
, numbers (including:0x...
,0b...
,...f
), strings with'string'
or"string"
(including raw strings usingr#"..."#
with variable number of#
, and hex strings withx'hex'
andx"hex"
and ). - Conditionals: if-then-else is support with the conditional (ternary) operator:
cond ? then-part : else-part
. - Object expression with
{
fields?}
, with optional fields, individual fields separated by,
(last entry can have a trailing,
):- fields can be
name: expr
with expr an expression or a primary data type (see above); - fields can be
"name": expr
with expr an expression or a primary data type (see above); - fields can be
field
(orfield???
), which copies the field from thethis
object; - fields can be
(expr): expr
to dynamically generate a field name (must be a string), e.g.{ (somefield): 42, }
(results in{x: 42}
ifsomefield
is"x"
).
- fields can be
- Array expressions:
[
expressions?]
, with the optionalexpressions
which are one or more expressions delimited by,
(last entry can have a trailing,
). Example:[ 42+42, 37+37, ]
. - Arithmetic operators:
+
,-
,*
,/
,**
(pow),%
(mod). - Bitwise operators:
|
,&
,^
(xor),<<
,>>
- Logical operators:
&&
,||
,a ? b : c
,==
,!=
,>
,>=
,<
,<=
. - Special
this
field, to signify current object. - Length operator:
field.len()
which result in the length of the field if it is a string (number of bytes), array (number of elements), or object (number of key-values).
- String operators:
a .. b
: concatenate stringsa
andb
;a *= b
: true if stringa
contains with stringb
a $= b
: true if stringa
ends with stringb
a ^= b
: true if stringa
starts with stringb
- Field operators:
a.b.c.d
is supported to access subfields;a[b][c][d]
is supported for dynamic subfields;
- Error operators:
- try operator:
a ??? b
: if there is an error during evaluation ofa
(like an undefined field, or division by zero). The shorthanda ???
is equivalent toa ??? null
. Alternative syntax istry(a, b)
andtry(a)
. - not-null-else operator:
a ?? b
: ifa
is null, returnb
.defined(x)
andundefined(x)
: checks if value is (un)defined (such as a field lookup).isnull(x)
checks ifx
is equal to null.
- try operator:
- Math functions:
pow(number)
- String methods:
.trim()
.lower()
.upper()
.hex()
.htmlescape()
.urlescape()
.sub(int[, int])
(third argument is length of resulting string, default the max integer value).basename()
.dirname()
.splitn(max, split_on)
(split_on is the splitting string, max is the max number of elements in the resulting array), results in an array of strings
- Type functions
tostring(any)
tointeger(any)
tofloat(any)
todouble(any)
User defined functions
During evaluation, there is also the possibility to add user defined functions. These user defined functions are only known at evaluation time, therefore there is no static type checking in place. Only runtime errors are generated if the number of arguments or type of arguments do not match.